using GeneralMinioApi.Models;
using GeneralMinioApi.Services;
using Microsoft.AspNetCore.Mvc;

namespace GeneralMinioApi.Controllers
{
    /// <summary>
    /// MinIO文件上传与下载接口
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    public class MinioController : ControllerBase
    {
        private readonly MinioService _minioService;
        private readonly IConfiguration _config;
        public MinioController(MinioService minioService, IConfiguration config)
        {
            _minioService = minioService;
            _config = config;
        }

        /// <summary>
        /// 上传文件到MinIO，自动按文件后缀归档到类型/日期目录
        /// </summary>
        /// <param name="file">要上传的文件（支持excel、word、png、jpg、pdf等）</param>
        /// <param name="bucketName">目标桶名称</param>
        /// <returns>上传结果及文件归档路径</returns>
        [HmacAuth]
        [HttpPost("upload")]
        public async Task<IActionResult> Upload(IFormFile file, [FromQuery] string bucketName)
        {
            if (file == null)
                return BadRequest("文件不能为空");

            if (bucketName == null)
            {
                return BadRequest("桶名称不能为空");
            }
            if (bucketName.Length < 3)
            {
                return BadRequest("桶名称长度至少为大于等于3");
            }

            await _minioService.EnsureBucketExistsAsync(bucketName);
            using var stream = file.OpenReadStream();
            var objectName = await _minioService.UploadFileAutoTypeAsync(file.FileName, stream, bucketName);

            // 获取MinIO直链
            var minioConfig = _config.GetSection("Minio");
            var endpoint = minioConfig["Endpoint"] ?? "";
            var url = $"http://{endpoint.Trim().Replace("http://", "").Replace("https://", "")}/{bucketName}/{objectName}";

            // 解析FileType
            var fileType = GetFileType(file.FileName);

            // 构建返回对象
            var response = new ResponseModel
            {
                Name = file.FileName,
                FilePath = url,
                FileSize = file.Length,
                Type = fileType
            };

            return Ok(response);
        }

        // 根据文件扩展名解析FileType
        private FileType GetFileType(string fileName)
        {
            var ext = Path.GetExtension(fileName).ToLowerInvariant();
            return ext switch
            {
                ".pdf" => FileType.Pdf,
                ".docx" => FileType.Docx,
                ".doc" => FileType.Doc,
                ".xlsx" => FileType.Xlsx,
                ".xls" => FileType.Xls,
                ".jpg" => FileType.Jpg,
                ".jpeg" => FileType.Jpeg,
                ".png" => FileType.Png,
                _ => FileType.Other
            };
        }

        /// <summary>
        /// 根据文件归档路径下载文件
        /// </summary>
        /// <param name="filePath">文件归档路径（如pdf/20240708/xxx.pdf）</param>
        /// <returns>文件流</returns>
        //  [HmacAuth]
        [HttpGet("download")]
        public async Task<IActionResult> Download([FromQuery] string url)
        {
            if (string.IsNullOrEmpty(url))
                return BadRequest("URL不能为空");

            try
            {
                var (bucketName, objectPath) = ParseMinioUrl(url);

                var stream = await _minioService.DownloadFileAsync(bucketName, objectPath);
                var fileName = Path.GetFileName(objectPath);

                return File(stream, "application/octet-stream", fileName);
            }
            catch (Exception ex)
            {
                return StatusCode(500, "文件下载失败");
            }
        }


        /// <summary>
        /// 获取服务器当前时间
        /// </summary>
        /// <returns>当前时间</returns>
        [HttpGet("server-time")]
        public IActionResult GetServerTime()
        {
            var serverTime = DateTime.UtcNow.ToString("yyyyMMddHHmm");
            var response = new ResponseServerTimeModel
            {
                ServerTime = serverTime
            };

            return Ok(response);
        }

        private (string BucketName, string ObjectPath) ParseMinioUrl(string url)
        {
            // 直接提取路径部分（不通过Uri类解码）
            int pathStart = url.IndexOf("//") + 2;
            pathStart = url.IndexOf('/', pathStart);
            string path = url.Substring(pathStart); // 如 "/general-files/png/20250702/%E5%B1%8F..."

            var segments = path.Split('/')
                            .Where(s => !string.IsNullOrEmpty(s))
                            .ToArray();

            if (segments.Length < 2)
                throw new ArgumentException("Invalid MinIO URL format");

            return (
                BucketName: segments[0], // general-files
                ObjectPath: string.Join("/", segments.Skip(1)) // 保持原始编码
            );
        }
    }
}